package tcp.socket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

/**
 * 这是一个单线程通讯的例子，由于没有额外执行accept，所以下一个连接连接上以后无法执行
 * 对于多线程来说，在accept之后，直接用新线程去处理下socket，
 * 默认支持50个连接,构造函数指定
 * 
 * 请求--->server队列---accept()-->取出以后执行，队列-1---->队列可以继续接收一个
 * @author Han
 */
public class Server {
	private static final int PORT = 1234;
	private ServerSocket serverSocket;
	private Map<Integer,Handler> users = new HashMap<Integer,Handler>();
	public Server() throws IOException{
		//没有指定长度的情况下，默认只能50个连接
		//同时可以设置绑定的ip地址，从而只允许局域网的连接
		//无参构造要先设置参数，再绑定端口。绑定端口后，参数设置将无效。
		serverSocket = new ServerSocket(PORT);
		System.out.println("server started...");
	}
	public void push(){
		for(Integer key : users.keySet()){
			users.get(key).push(key+",你好");
			System.out.println("发送消息"+key);
		}
	}
	private PrintWriter getWriter(Socket socket) throws IOException{
		OutputStream os = socket.getOutputStream();
		return new PrintWriter(os, true);
	}
	
	private BufferedReader getReader(Socket socket) throws IOException{
		InputStream is = socket.getInputStream();
		return new BufferedReader(new InputStreamReader(is));
	}
	
	public void service(){
		int i =1;
		while(true){
			Socket socket = null;
			try {
				socket = serverSocket.accept();
				Handler tmp = new Handler(socket);
				users.put(i, tmp);
				new Thread(tmp,i+"个线程").start();
				i++;
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	
	class Handler implements Runnable{
		private Socket socket;
		public Handler(Socket socket){
			this.socket = socket;
		}
		
		private PrintWriter getWriter(Socket socket) throws IOException{
			OutputStream os = socket.getOutputStream();
			return new PrintWriter(os, true);
		}
		
		private BufferedReader getReader(Socket socket) throws IOException{
			InputStream is = socket.getInputStream();
			return new BufferedReader(new InputStreamReader(is));
		}
		public void push(String msg){
			PrintWriter pw;
			try {
				pw = getWriter(socket);
				pw.println(msg);
				pw.flush();
				System.out.println("send...");
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		@Override
		public void run() {
			try {
				BufferedReader br = getReader(socket);
				PrintWriter pw = getWriter(socket);
				String msg = null;
				while((msg = br.readLine()) != null){
					System.out.println("recieve:"+msg);
					pw.println(System.currentTimeMillis());
					if(msg.equals("bye")){
						break;
					}
				}
			} catch (IOException e) {
				e.printStackTrace();
			}finally{
				if(socket != null){
					try {
						socket.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
	//
	public static void main(String[] args) {
		try {
			final Server server = new Server();
			new Thread(){
				public void run() {
					System.out.println(".....");
					while(true){
						try {
							sleep(5000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						server.push();
					}
				};
			}.start();
			server.service();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
